package com.zhongmai.yzfgrabanorder.netty_lib.netty;

import android.os.Message;
import android.util.Log;

import com.google.gson.Gson;
import com.zhongmai.yzfgrabanorder.fragment.FragmentsManager;
import com.zhongmai.yzfgrabanorder.fragment.GrabAnOrderFragment;
import com.zhongmai.yzfgrabanorder.netty_lib.bean.ChatInfo;
import com.zhongmai.yzfgrabanorder.netty_lib.bean.NettyBaseFeed;
import com.zhongmai.yzfgrabanorder.utils.Constants;

import java.util.Stack;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;

/**
 * Created by 张俨 on 2018/1/10.
 */

public class NettyClientHandler extends SimpleChannelInboundHandler<String> {
    private static final String TAG = NettyClientHandler.class.getName();
    private NettyListener listener;

    public NettyClientHandler(NettyListener listener) {
        this.listener = listener;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        NettyClient.getInstance().setConnectStatus(true);
        listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_SUCCESS);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Constants.online = false;
        Log.e(TAG, "channelInactive 连接失败");
        NettyClient.getInstance().setConnectStatus(false);
        listener.onServiceStatusConnectChanged(NettyListener.STATUS_CONNECT_CLOSED);
        if (Constants.manual_link) {
            NettyClient.getInstance().reconnect();
        }
        /**
         * 服务端断开链接，改变按钮
         */
        Stack<GrabAnOrderFragment> fragments = FragmentsManager.getInstance().getFragments();
        for (GrabAnOrderFragment fragment : fragments) {
            if (fragment == null || !fragment.isVisible()) {
                continue;
            }
            Message message = Message.obtain();
            message.what = 1;
            fragment.getHandler().sendMessage(message);
        }
    }

    /**
     * 消息回调，服务器心跳也会接收
     *
     * @param channelHandlerContext
     * @param byteBuf
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String byteBuf) throws Exception {
        Log.e(TAG, "来自服务器的消息 ====》" + byteBuf);
        listener.onMessageResponse(byteBuf);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        Log.i(TAG, "链接错误");
        cause.printStackTrace();
        ctx.close(); //关闭连接后回调channelInactive会重新调用connectService.connect();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            if (idleStateEvent.state().equals(IdleState.WRITER_IDLE)) {
                //写超时，此时可以发送心跳数据给服务器
                Log.d(TAG, "userEventTriggered write idle");
                //                if (connectService == null){
                //                    return;
                //                }
                sendHeartPkg(ctx);
            } else if (idleStateEvent.state().equals(IdleState.READER_IDLE)) {
                //读超时，此时代表没有收到心跳返回可以关闭当前连接进行重连
                Log.d(TAG, "userEventTriggered read idle");
                ctx.channel().close();
            }
        }
    }

    /**
     * 发送心跳
     */
    private void sendHeartPkg(ChannelHandlerContext ctx) {
        final NettyBaseFeed<ChatInfo> baseFeed = new NettyBaseFeed<>();
        baseFeed.setCmd("heartbeat");
        baseFeed.setMessage("20秒心跳检测");
        final ChatInfo chatInfo = new ChatInfo();
        chatInfo.setUser(Constants.user);
        baseFeed.setData(chatInfo);
        String s = new Gson().toJson(baseFeed);
        ctx.channel().writeAndFlush(s + "\n");
        Log.d(TAG, "客户端发送心跳成功");
    }
}
